<script setup lang="tsx">
import type { TreeOption } from 'naive-ui';
import { NButton, NPopconfirm, NTag } from 'naive-ui';
import { usePagination } from '@sa/alova/client';
import { computed, onMounted, reactive, ref, shallowRef } from 'vue';
import { batchDelArticle, deleteArticle, paginateArticle, treeColumn } from '@/service/api/cms';
import { $t } from '@/locales';
import { useAppStore } from '@/store/modules/app';
import useCheckedColumns from '@/hooks/common/table/table-columns';
import useTableOperate from '@/hooks/common/table/table-operate';
import PorDictTag from '@/components/_builtin/por-dict-tag/index.vue';
import ArticleSearch from './modules/article-search.vue';
import ArticleDrawer from './modules/article-drawer.vue';

const appStore = useAppStore();

const emptyNode: Api.Node = { id: '', parentId: '', children: null, name: '' };
const columnNode = ref(emptyNode as Api.Model);
const columnData = shallowRef<TreeOption[]>([]);
const siteId = ref<number | null>(null);
interface SearchParams {
  id: number | null;
  columnId: number | null;
  status: number | null;
  siteId: number | null;
  title: string | null;
}
const searchParams = reactive({
  id: null,
  columnId: null,
  status: null,
  siteId: null,
  title: ''
} as SearchParams);

async function getColumnData() {
  const data = await treeColumn({ siteId: siteId.value, status: 1 });
  if (data) {
    console.log(data);
    columnData.value = data.map(recursive);
    columnNode.value = emptyNode as Api.Model;
  }
}

onMounted(() => {
  getColumnData();
});

function recursive(item: Api.Node): TreeOption {
  const result: TreeOption = {
    ...item,
    children: item.children ? item.children.map(recursive) : undefined
  };

  return result;
}

function changeSite(value: Array<string | number> | string | number | null) {
  if (value) {
    siteId.value = value as number;
    searchParams.siteId = siteId.value;
  } else {
    siteId.value = null;
    searchParams.siteId = null;
  }

  getColumnData();
}

const { loading, data, page, pageSize, pageCount, refresh, send, remove } = usePagination(
  (p, sz) =>
    paginateArticle({
      ...searchParams,
      pageNumber: p,
      pageSize: sz
    }),
  {
    data: ({ records }) => {
      console.log(records);

      return records;
    },
    total: ({ total }) => total,
    watchingStates: [searchParams],
    debounce: [500]
  }
);

const searchPaginate = (newPage = 1) => {
  page.value = newPage;
  send(page.value, pageSize.value);
};

/** tree select handle */
async function handleSelectKeys(node: TreeOption | null, action: string) {
  // 点击一次是选择select, 再点击一次是unselect
  if (action === 'select' && node) {
    searchParams.columnId = node.id as number;
    columnNode.value = node as Api.Model;
  } else {
    searchParams.columnId = null;
  }

  searchPaginate(1);
}

const {
  drawerVisible,
  operateType,
  editingData,
  handleAdd,
  handleEdit,
  handleDelete,
  handleBatchDelete,
  checkedRowKeys,
  deleting
} = useTableOperate(data, {
  async delete(row) {
    await deleteArticle({ id: row.id });
    remove(row);
  },
  async batchDelete(rows) {
    await batchDelArticle({ ids: rows.map(row => row.id) });
    remove(...rows);
  }
});

function edit(id: number) {
  handleEdit(id);
}

const { columnChecks, columns } = useCheckedColumns<typeof paginateArticle>(() => [
  {
    type: 'selection',
    align: 'center',
    width: 40
  },
  {
    key: 'title',
    title: '标题',
    align: 'center',
    width: 200
  },
  {
    key: 'columnName',
    title: '栏目',
    align: 'center',
    width: 100
  },
  {
    key: 'siteName',
    title: '站点',
    align: 'center',
    width: 100
  },

  {
    key: 'clickNum',
    title: '点击数',
    align: 'center',
    width: 60
  },
  {
    key: 'favoriteNum',
    title: '收藏数',
    align: 'center',
    width: 60
  },
  {
    key: 'likeNum',
    title: '点赞数',
    align: 'center',
    width: 60
  },
  {
    key: 'pinTop',
    title: '置顶',
    align: 'center',
    width: 60,
    render: row => {
      if (row.pinTop === null) {
        return <NTag></NTag>;
      }
      return <PorDictTag dict-code="common_yes_no" value={row.pinTop} valueToNumber></PorDictTag>;
    }
  },
  {
    key: 'status',
    title: '状态',
    align: 'center',
    width: 60,
    render: row => {
      if (row.status === null) {
        return <NTag></NTag>;
      }
      return <PorDictTag dict-code="cms_article_status" value={row.status}></PorDictTag>;
    }
  },
  {
    key: 'createTime',
    title: '创建时间',
    align: 'center',
    width: 120
  },
  {
    key: 'operate',
    title: $t('common.operate'),
    align: 'center',
    width: 130,
    fixed: 'right',
    render: row => (
      <div class="flex-center gap-8px">
        <NButton type="primary" ghost size="small" onClick={() => edit(row.id as number)}>
          {$t('common.edit')}
        </NButton>
        <NPopconfirm
          onPositiveClick={() => handleDelete(row.id)}
          positiveButtonProps={{
            loading: deleting.value
          }}
        >
          {{
            default: () => $t('common.confirmDelete'),
            trigger: () => (
              <NButton type="error" ghost size="small">
                {$t('common.delete')}
              </NButton>
            )
          }}
        </NPopconfirm>
      </div>
    )
  }
]);

const paginationConfig = computed(() => ({
  page: page.value,
  pageSize: pageSize.value,
  showSizePicker: true,
  pageCount: pageCount.value,
  pageSizes: [10, 15, 20, 25, 30],
  onUpdatePage: (value: number) => {
    page.value = value;
  },
  onUpdatePageSize: (value: number) => {
    pageSize.value = value;
  }
}));
</script>

<template>
  <div class="flex">
    <NSplit :size="0.2" default-size="240px" pane1-class="pr-2" pane2-class="pl-2" :resize-trigger-size="0">
      <template #1>
        <div class="min-h-500px flex-col-stretch gap-16px overflow-hidden lt-sm:overflow-auto">
          <NCard :bordered="false" size="small" class="sm:flex-1-hidden card-wrapper">
            <template #header>
              <PorSelect
                v-model:value="siteId"
                placeholder="请选择站点"
                url="/cms/site/simpleList?status=1"
                label-field="name"
                value-field="id"
                value-to-number
                filterable
                class="user-select"
                size="small"
                @update:value="changeSite"
              ></PorSelect>
            </template>
            <NScrollbar class="m-t-2 max-h-690px min-h-690px">
              <NTree
                :data="columnData"
                block-line
                key-field="id"
                label-field="name"
                :show-irrelevant-nodes="false"
                class="gap-16px"
                @update-selected-keys="(_key, _option, { node, action }) => handleSelectKeys(node, action)"
              />
            </NScrollbar>
          </NCard>
        </div>
      </template>
      <template #2>
        <div class="min-h-500px flex-col-stretch gap-16px overflow-hidden lt-sm:overflow-auto">
          <ArticleSearch v-model:model="searchParams" @search="searchPaginate" />
          <NCard title="文章表" :bordered="false" size="small" class="sm:flex-1-hidden card-wrapper">
            <template #header-extra>
              <TableHeaderOperation
                v-model:columns="columnChecks"
                :disabled-delete="checkedRowKeys.length === 0"
                :loading="loading"
                @add="handleAdd"
                @delete="handleBatchDelete"
                @refresh="refresh"
              />
            </template>
            <NDataTable
              v-model:checked-row-keys="checkedRowKeys"
              :columns="columns"
              :data="data"
              size="small"
              :flex-height="!appStore.isMobile"
              :scroll-x="962"
              :loading="loading"
              remote
              :row-key="row => row.id"
              :pagination="paginationConfig"
              class="sm:h-full"
              min-height="480px"
            />
            <ArticleDrawer
              v-model:visible="drawerVisible"
              :operate-type="operateType"
              :row-data="editingData"
              @submitted="refresh"
            />
          </NCard>
        </div>
      </template>
    </NSplit>
  </div>
</template>

<style scoped></style>
